package com.example.springbooteasycode.utils.word;

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Objects;

/**
 * 根据模版生成Word文档
 * @author csa
 */
public class WordGeneratorUtil {
    public static void generateWordDocument(Object dataModel, String templatePath, String outputPath) throws IOException {
        // 通过类加载器获取输入流（推荐）
        InputStream templateStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(templatePath);
        XWPFDocument document = new XWPFDocument(templateStream);

        // 处理所有段落
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            processParagraph(paragraph, dataModel);
        }
        // 处理所有表格
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        processParagraph(paragraph, dataModel);
                    }
                }
            }
        }
        try (FileOutputStream out = new FileOutputStream(outputPath)) {
            document.write(out);
        }

        document.close();
    }

    private static void processParagraph(XWPFParagraph paragraph, Object dataModel) {
        List<XWPFRun> runsCopy = new ArrayList<>(paragraph.getRuns());
        for (XWPFRun run : runsCopy) {
            String text = run.getText(0);
            if (text != null && text.contains("${sign}")) {
                // 处理签名图片替换
                handleBase64ImageReplacement(run, dataModel);
            } else if (text!=null && text.contains("${electronicPhoto}")){
                // 一寸照图片替换
                handleImageReplacement(run, dataModel);
            } else {
                // 处理普通文本替换
                handleTextReplacement(run, dataModel);
            }
        }
    }


    private static void handleImageReplacement(XWPFRun run, Object dataModel) {
        try {
            Field signField = dataModel.getClass().getDeclaredField("electronicPhoto");
            signField.setAccessible(true);
            String filepath = (String) signField.get(dataModel);
            if (filepath == null || filepath.isEmpty()){
                return;
            }
            File imageFile = new File(filepath);
            // 删除原有占位符文本
            run.setText("", 0);
            if (imageFile.exists()) {
                // 使用图片文件流
                try (InputStream imageStream = new FileInputStream(imageFile)) {
                    int imageType = detectImageTypeByFileExtension(imageFile);
                    // 设置图片大小为一寸照片标准尺寸（大约）  约等于25mm  26400EMU  约等于35mm 36780EMU
                    int widthInEmu = Units.toEMU(70);
                    int heightInEmu = Units.toEMU(98);
                    run.addPicture(imageStream,
                            imageType,
                            imageFile.getName(),
                            widthInEmu,
                            heightInEmu);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void handleBase64ImageReplacement(XWPFRun run, Object dataModel) {
        try {
            Field signField = dataModel.getClass().getDeclaredField("sign");
            signField.setAccessible(true);
            String base64Image = (String) signField.get(dataModel);
            if (base64Image != null && !base64Image.isEmpty()) {
                // 获取原始文本
                String text = run.getText(0);

                // 分割文本
                int placeholderStart = text.indexOf("${sign}");
                String beforePlaceholder = text.substring(0, placeholderStart);
                String afterPlaceholder = text.substring(placeholderStart + "${sign}".length());

                // 删除原有占位符文本
                run.setText(beforePlaceholder, 0);

                // Base64解码
                byte[] imageBytes = Base64.getDecoder().decode(base64Image.split(",")[1]);

                // 添加图片（自动检测图片类型）
                try (InputStream imageStream = new ByteArrayInputStream(imageBytes)) {
                    int imageType = detectImageType(base64Image);
                    // 在原有run之后插入图片
                    XWPFParagraph paragraph = run.getParagraph();
                    XWPFRun imageRun = paragraph.insertNewRun(paragraph.getRuns().indexOf(run) + 1);
                    imageRun.addPicture(imageStream,
                            imageType,
                            "signature.png",
                            // 宽度
                            Units.toEMU(43),
                            // 高度
                            Units.toEMU(30));
                    // 插入占位符之后的文本
                    XWPFRun afterTextRun = paragraph.insertNewRun(paragraph.getRuns().indexOf(imageRun) + 1);
                    afterTextRun.setText(afterPlaceholder);
                    // 复制原有run的样式到新run
                    copyRunProperties(run, afterTextRun);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static int detectImageTypeByFileExtension(File imageFile) throws IOException {
        String fileName = imageFile.getName().toLowerCase();
        if (fileName.endsWith(ImageFileTypeSuffixEnum.PNG.getName())) {
            return XWPFDocument.PICTURE_TYPE_PNG;
        } else if (fileName.endsWith(ImageFileTypeSuffixEnum.JPG.getName()) || fileName.endsWith(ImageFileTypeSuffixEnum.JPEG.getName())) {
            return XWPFDocument.PICTURE_TYPE_JPEG;
        } else if (fileName.endsWith(ImageFileTypeSuffixEnum.GIF.getName())) {
            return XWPFDocument.PICTURE_TYPE_GIF;
        } else {
            throw new IOException("不支持的图片格式: " + imageFile.getName());
        }
    }
    private static int detectImageType(String base64) {
        if (base64.startsWith(ImageFileTypeBase64PrefixEnum.PNG.getName())) {
            return XWPFDocument.PICTURE_TYPE_PNG;
        } else if (base64.startsWith(ImageFileTypeBase64PrefixEnum.JPEG.getName())) {
            return XWPFDocument.PICTURE_TYPE_JPEG;
        } else if (base64.startsWith(ImageFileTypeBase64PrefixEnum.GIF.getName())) {
            return XWPFDocument.PICTURE_TYPE_GIF;
        }
        // 默认PNG格式
        return XWPFDocument.PICTURE_TYPE_PNG;
    }

    private static void handleTextReplacement(XWPFRun originalRun, Object dataModel) {
        String text = originalRun.getText(0);
        if (text != null) {
            // 1. 替换占位符
            for (Field field : dataModel.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                try {
                    Object value = field.get(dataModel);
                    if (value != null && !field.getName().equals("sign") && !field.getName().equals("electronicPhoto")) {
                        String placeholder = "${" + field.getName() + "}";
                        if (text.contains(placeholder)) {
                            text = text.replace(placeholder, value.toString());
                            originalRun.setText(text, 0);
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            // 2. 清理未匹配的占位符
            text = text.replaceAll("\\$\\{[^}]+\\}", "");

            // 3. 将文本按换行符分割并插入文档
            String[] lines = text.split("\n");
            XWPFParagraph paragraph = originalRun.getParagraph();
            int position = paragraph.getRuns().indexOf(originalRun);
            originalRun.setText("", 0);

            for (String line : lines) {
                if (!line.trim().isEmpty()) {
                    XWPFRun newRun = position < paragraph.getRuns().size() - 1 ?
                            paragraph.insertNewRun(position++) : paragraph.createRun();
                    newRun.setText(line);
                    // 复制原run的样式到新run
                    copyRunProperties(originalRun, newRun);

                    if (!line.equals(lines[lines.length - 1])) {
                        newRun.addBreak();
                    }
                }
            }
        }
    }
    private static void copyRunProperties(XWPFRun source, XWPFRun target) {
        // 根据需求复制源run的属性到目标run，例如字体、大小等
        target.setFontFamily(source.getFontFamily());
        target.setFontSize(source.getFontSize());
    }
}
